<template>
  <ToolbarButton
    type="select"
    :model-value="currentFontFamily"
    :options="fontOptions"
    placeholder="选择字体"
    select-width="134px"
    filterable
    @update:model-value="handleFontChange"
  >
    <template #option="{ option }">
      <div class="font-option-content font-family-option">
        <span
          class="font-preview"
          :style="{
            fontFamily: option.value === 'default' ? 'inherit' : option.value,
          }"
        >
          {{ option.label }}
        </span>
        <span
          v-if="!fontDetect(option.value)"
          class="font-unavailable"
          title="字体不可用"
        >
          !
        </span>
      </div>
    </template>
  </ToolbarButton>
</template>

<script setup lang="ts">
import { inject, computed, ref, watch, type Ref } from "vue";
import type { Editor } from "@tiptap/vue-3";
import type { EditorProps } from "../../../../types";
import ToolbarButton from "../../../button/index.vue";
import { defaultDicts } from "../../../../config/constants";

defineOptions({
  name: "FontFamily",
});

// 注入依赖
const editor = inject<Ref<Editor>>("editor");
const editorProps = inject<EditorProps>("editorProps");

// 状态管理
const recentFonts = ref<string[]>([]);
const usedFonts = ref<string[]>([]);

// 字体检测功能（像素对比法，和示例一致，更稳定）
const fontDetect = (font?: string) => {
  if (!font || font === "default") {
    return true;
  }

  const baseFont = "fontname";
  const testChar = "text";
  const canvasWidth = 100;
  const canvasHeight = 100;

  const canvas = document.createElement("canvas");
  const context = canvas.getContext("2d", {
    willReadFrequently: true,
  }) as CanvasRenderingContext2D | null;

  canvas.width = canvasWidth;
  canvas.height = canvasHeight;
  if (context) {
    context.textAlign = "center";
    context.fillStyle = "black";
    context.textBaseline = "middle";
  }

  const getImageDataWithFont = (currentFont: string) => {
    if (!context) {
      return [] as number[];
    }
    context.clearRect(0, 0, canvasWidth, canvasHeight);
    context.font = `${canvasHeight}px ${currentFont}, ${baseFont}`;
    context.fillText(testChar, canvasWidth / 2, canvasHeight / 2);
    const { data } = context.getImageData(0, 0, canvasWidth, canvasHeight);

    return Array.from(data).filter((pixel) => pixel !== 0);
  };

  return (
    getImageDataWithFont(baseFont).join("") !==
    getImageDataWithFont(font).join("")
  );
};

// 获取文档中已使用的字体
const extractUsedFonts = (): void => {
  if (!editor?.value) return;

  try {
    const content = JSON.stringify(editor.value.getJSON());
    const fontMatches = content.match(/"fontFamily":"([^"]+)"/g);

    if (fontMatches) {
      const fonts = fontMatches.map((match) =>
        match.replace('"fontFamily":"', "").replace('"', "")
      );

      usedFonts.value = [...new Set(fonts)];
    }
  } catch (error) {
    console.warn("Failed to extract used fonts:", error);
  }
};

// 更新最近使用的字体
const updateRecentFonts = (fontName: string): void => {
  if (fontName === "default") return;

  const index = recentFonts.value.indexOf(fontName);
  if (index > -1) {
    recentFonts.value.splice(index, 1);
  }

  recentFonts.value.unshift(fontName);

  // 限制最近使用字体数量
  if (recentFonts.value.length > 8) {
    recentFonts.value = recentFonts.value.slice(0, 8);
  }
};

// Label 统一转字符串，根据 locale 选择对应的语言，兜底为 value
const normalizeLabel = (label: any, fallback: string): string => {
  if (typeof label === "string") {
    return label && label.trim() ? label : fallback;
  }
  if (label && typeof label === "object") {
    const locale = editorProps?.locale || "zh-CN";
    // 根据 locale 选择对应的语言标签
    if (locale === "zh-CN" && label.zh_CN) {
      return label.zh_CN;
    }
    if (locale === "en-US" && label.en_US) {
      return label.en_US;
    }
    // 如果当前语言没有，则尝试另一个语言，最后使用 fallback
    return label.zh_CN || label.en_US || fallback;
  }
  return fallback;
};

// 获取所有有效字体，过滤掉空 value，统一 label
const getAllFonts = () => {
  const raw = editorProps?.dicts?.fonts || defaultDicts.fonts || [];
  return (raw || [])
    .map((item: any) => {
      const value = (item?.value ?? "") as string;
      if (!value) return null;
      return {
        label: normalizeLabel(item?.label, value),
        value,
      };
    })
    .filter(Boolean) as Array<{ label: string; value: string }>;
};

// 根据字体值获取字体信息
const getFontInfo = (fontValue: string) => {
  const allFonts = getAllFonts();
  const found = allFonts.find((font) => font.value === fontValue);
  if (found) return found;
  return { label: fontValue, value: fontValue };
};

// 字体选项计算
const fontOptions = computed(() => {
  const allFonts = getAllFonts();
  const options: Array<{ label: string; value: string; disabled?: boolean }> =
    [];

  // 最近使用的字体
  if (recentFonts.value.length > 0) {
    recentFonts.value.forEach((fontValue) => {
      const fontInfo = getFontInfo(fontValue);
      options.push({
        ...fontInfo,
        disabled: !fontDetect(fontValue),
      });
    });

    // 添加分隔符（如果还有其他字体）
    if (allFonts.length > 0) {
      options.push({
        label: "────────────",
        value: "__sep_recent__",
        disabled: true,
      });
    }
  }

  // 已使用的字体（排除最近使用的）
  const remainingUsedFonts = usedFonts.value.filter(
    (font) => !recentFonts.value.includes(font)
  );

  if (remainingUsedFonts.length > 0) {
    remainingUsedFonts.forEach((fontValue) => {
      const fontInfo = getFontInfo(fontValue);
      options.push({
        ...fontInfo,
        disabled: !fontDetect(fontValue),
      });
    });

    // 添加分隔符
    if (allFonts.length > 0) {
      options.push({
        label: "────────────",
        value: "__sep_used__",
        disabled: true,
      });
    }
  }

  // 所有字体
  allFonts.forEach((font) => {
    if (
      !recentFonts.value.includes(font.value) &&
      !usedFonts.value.includes(font.value)
    ) {
      const fontInfo = getFontInfo(font.value);
      options.push({
        ...fontInfo,
        disabled: !fontDetect(font.value),
      });
    }
  });

  return options;
});

// 获取默认字体（优先使用微软雅黑）
const getDefaultFont = computed(() => {
  const allFonts = getAllFonts();
  // 优先查找微软雅黑
  const yaheiFont = allFonts.find(
    (font) => font.value === "微软雅黑" || font.value === "Microsoft Yahei"
  );
  if (yaheiFont) {
    return yaheiFont.value;
  }
  // 如果没有微软雅黑，返回第一个有效字体
  const validFonts = allFonts.filter(
    (font) => font.value && font.value !== "default"
  );
  if (validFonts.length > 0) {
    return validFonts[0].value;
  }
  // 如果还是没有，尝试从 defaultDicts.fonts 获取（排除 null 值）
  const defaultFontsList = editorProps?.dicts?.fonts || defaultDicts.fonts || [];
  const defaultValidFont = defaultFontsList.find(
    (f: any) => f.value && f.value !== "default" && f.value !== null
  );
  return defaultValidFont?.value || "default";
});

// 当前字体计算
const currentFontFamily = computed(() => {
  if (!editor?.value) return getDefaultFont.value;

  const fontFamily = editor.value.getAttributes("textStyle").fontFamily;
  // 如果有字体，返回字体值；如果没有，返回第一个可用字体作为显示值
  return fontFamily || getDefaultFont.value;
});

// 字体变化处理
const handleFontChange = (fontFamily: string): void => {
  if (!editor?.value) return;

  // 跳过分隔符
  if (fontFamily.startsWith("__sep_")) return;

  if (fontFamily && fontFamily !== "default") {
    editor.value.chain().focus().setFontFamily(fontFamily).run();
    updateRecentFonts(fontFamily);
  } else {
    editor.value.chain().focus().unsetFontFamily().run();
  }

  // 更新已使用字体
  extractUsedFonts();
};

// 监听编辑器变化
watch(
  () => editor?.value,
  (newEditor) => {
    if (newEditor) {
      extractUsedFonts();
    }
  },
  { immediate: true }
);
</script>

<style scoped>
.font-family-option {
  padding: 0 !important;
}

.font-option-content {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  padding: 8px 12px;
  font-size: 14px;
}

.font-preview {
  flex: 1;
  font-size: 14px;
  line-height: 1.4;
}

.font-unavailable {
  color: #f56c6c;
  font-size: 14px;
  font-weight: bold;
  margin-left: 8px;
  opacity: 0.8;
}

/* 分隔符样式 */
:deep(.el-option.is-disabled) {
  color: #c0c4cc !important;
  cursor: default !important;
  background: transparent !important;
}

:deep(.el-option.is-disabled:hover) {
  background: transparent !important;
}
</style>
